package cn.tedu.v6;

import java.io.*;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;

/**
 * Version 6在线用户列表
 */


    public class Server {
    private ServerSocket serverSocket;
    private static final  Integer PORT=5588;
    private List<PrintWriter> allOut=new ArrayList<>();
    //1.私有化集合保存所有用户名---onlineUsers
    private Map<String,String> userDataBase;
       private Set<String> onlineUsers = Collections.synchronizedSet(new HashSet<>());

    public Server() {
    try {
    serverSocket = new ServerSocket(PORT);

    userDataBase=new HashMap<>();
    userDataBase.put("吵吵","19890411");
    userDataBase.put("嘻嘻","20051222");
    } catch (BindException e) {
    System.out.println("端口号重复申请，建议换个端口号");
    } catch (IOException e) {
    System.out.println("申请端口号失败...");
    }
    }

    public void start() {
    try {
    while (true) {
    System.out.println("----等待客户端链接----");
    Socket socket = serverSocket.accept();
    System.out.println(socket+"12345");
    String ip = socket.getInetAddress().getHostAddress();
    System.out.println(ip + "客户端链接成功了~~");
    new Thread(new ClientHandler(socket)).start();
    }
    } catch (IOException e) {
    System.out.println("服务器端通讯断开了");
    } finally {
    if(serverSocket!=null&&!serverSocket.isClosed()){
    try {
    serverSocket.close();
    } catch (IOException e) {
    System.out.println("服务器关闭失败");
    }
    }
    }
    }

    public static void main(String[] args) {
    new Server().start();
    }
    private synchronized void broadcastMessage(String message) {
    for (PrintWriter pw:allOut){
    pw.println("消息广播"+message);
    }
    }
    //2.封装方法：同步转发给所有客户端消息：“在线用户：”+username
    //updateOnlineUsers  更新在线人名单的办法：“在线用户：”+username
    //字符串：String userList="在线用户"+String.join("、",onlineUsers)
        private synchronized void updateOnlineUsers(String username) {
        onlineUsers.add(username);
        String userList = "在线用户: " + String.join("、", onlineUsers);
        broadcastMessage(userList);
        }
    private class ClientHandler implements Runnable {
    private Socket socket;
    private String ip;
    private BufferedReader br;
    private PrintWriter pw;

    private String username;
    private String password;
    public ClientHandler(Socket s) {
    this.socket = s;
    ip = socket.getInetAddress().getHostAddress();
    try {
    br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF8"));
    pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF8")), true);
    synchronized (allOut) {
    allOut.add(pw);
    }
    } catch (IOException e) {
    System.out.println("客户端断开通讯");
    }
    }

    private boolean Login(String user,String pass){
    //userDataBase.containsKey(user)  判断账号存在
    return userDataBase.containsKey(user)&&userDataBase.get(user).equals(pass);
    }

    private void handlerChat() {
    new Thread(() -> {
    try {
    String message;
    while ((message = br.readLine()) != null) {

    System.out.println("客户端说" + message);
    System.out.println("服务器请输入：");
    broadcastMessage(message);
    }
    } catch (IOException e) {
    System.out.println("客户端读入失败！");
    e.printStackTrace();
    }
    }).start();
    Scanner input = new Scanner(System.in);
    while (true) {
    System.out.println(ip + "恭喜你抽中五百万！");
    String say = input.nextLine();
    pw.println("服务器说"+say);
    }
    }
    public void run() {
    try {

    pw.println("请输入用户名：");
    username=br.readLine();

    pw.println("请输入密码：");
    password=br.readLine();

    if (Login(username,password)) {
    System.out.println("11111");
    pw.println("登陆成功，欢迎进入聊天室~");
    System.out.println("22222");
    //3.把所有用户添加至集合中【同步】
         updateOnlineUsers(username);
    handlerChat();
    }else{
    pw.println("登陆失败，账用户名或密码不正确！");
    socket.close();
    }
    } catch (NullPointerException e) {
    System.out.println("IO流传入对象，有对象为null，立马核对，建议：查看try块中对象可能赋值为null");
    }catch (IOException e) {
    System.out.println("服务器端断开连接");
    } finally {
    //4.客户端断开链接，移除当前集合【同步】
    synchronized (allOut) {
    allOut.remove(pw);
    }
    if (br!=null)
    try {
    br.close();
    } catch (IOException e) {
    System.out.println("结束通讯：关闭失败！");
    }
    if (pw != null)
    pw.close();
    if (socket!= null&&!socket.isClosed())
    try {
    socket.close();
    } catch (IOException e) {
    System.out.println("通讯关闭，关闭失败");
    }
    }
    }
    }
    }

